using B.S.NewMedical.Api.Write.Application.Command.Payment;
using B.S.NewMedical.Domain.Appointment;
using B.S.NewMedical.Domain.Doctor;
using B.S.NewMedical.Infrastructure;
using B.S.NewMedical.Infrastructure.Interface;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace B.S.NewMedical.Api.Write.Application.Handler.Payment
{
    public class PayForTestHandler : IRequestHandler<PayForTestCommand, int>
    {
        private readonly ILogger<PayForTestHandler> _logger;
        private readonly IBaseRepository<MedicalCard> _medicalCardRepository;
        private readonly IBaseRepository<Charge> _chargeRepository;
        private readonly IBaseRepository<PrescriptionApplicationModel> _prescriptionApplicationRepository;
        private readonly MyDbcontext _context;

        public PayForTestHandler(
            ILogger<PayForTestHandler> logger,
            IBaseRepository<MedicalCard> medicalCardRepository,
            IBaseRepository<Charge> chargeRepository,
            IBaseRepository<PrescriptionApplicationModel> prescriptionApplicationRepository,
            MyDbcontext context)
        {
            _logger = logger;
            _medicalCardRepository = medicalCardRepository;
            _chargeRepository = chargeRepository;
            _prescriptionApplicationRepository = prescriptionApplicationRepository;
            _context = context;
        }

        public async Task<int> Handle(PayForTestCommand request, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation($"开始处理检验支付，患者ID: {request.PatientId}, 金额: {request.Amount}");

                // 基本参数验证
                if (request.PatientId <= 0)
                    throw new ArgumentException("患者ID不能为空");

                if (request.Amount <= 0)
                    throw new ArgumentException("支付金额必须大于0");

                if (string.IsNullOrEmpty(request.PayChannel))
                    throw new ArgumentException("支付方式不能为空");

                // 验证开单申请表ID是否存在
                var prescriptionApplication = await _prescriptionApplicationRepository.GetValue(request.PrescriptionApplicationId);
                if (prescriptionApplication == null || prescriptionApplication.IsDeleted)
                    throw new ArgumentException($"开单申请表ID不存在：{request.PrescriptionApplicationId}");

                // 通过患者ID查找医疗卡
                var medicalCard = await _medicalCardRepository.GetAll()
                    .FirstOrDefaultAsync(c => c.Patient_id == request.PatientId && !c.IsDeleted, cancellationToken);

                if (medicalCard == null)
                    throw new InvalidOperationException($"未找到患者ID {request.PatientId} 的医疗卡");

                // 检查医疗卡余额
                if (medicalCard.Card_price < request.Amount)
                    throw new InvalidOperationException($"医疗卡余额不足，当前余额: {medicalCard.Card_price}，需要支付: {request.Amount}");

                using var transaction = await _context.Database.BeginTransactionAsync(cancellationToken);
                try
                {
                    // 扣除医疗卡余额
                    medicalCard.Card_price -= request.Amount;
                    await _medicalCardRepository.UpdateAsync(medicalCard);

                    // 创建收费记录（不依赖就诊记录）
                    var charge = new Charge
                    {
                        Visit_id = 0, // 使用0表示不关联具体就诊记录
                        Total_amount = request.Amount,
                        Discount = 0,
                        Real_amount = request.Amount,
                        Pay_channel = request.PayChannel,
                        Pay_time = DateTime.Now,
                        Cashier_id = request.CashierId,
                        status = "已收费",
                        IsDeleted = false
                    };

                    await _chargeRepository.CreateAsync(charge);

                    // 更新开单申请状态为已支付，并更新患者ID
                    prescriptionApplication.Status = 3; // 已支付
                    prescriptionApplication.PaymentTime = DateTime.Now;
                    prescriptionApplication.PatientId = request.InputPatientId; // 更新为传入的患者ID
                    _context.PrescriptionApplicationModel.Update(prescriptionApplication);
                    _logger.LogInformation($"开单申请状态已更新为已支付，申请ID: {request.PrescriptionApplicationId}，患者ID已更新为: {request.InputPatientId}");

                    await _context.SaveChangesAsync(cancellationToken);
                    await transaction.CommitAsync(cancellationToken);

                    _logger.LogInformation($"检验支付成功，收费记录ID: {charge.Id}");
                    return charge.Id;
                }
                catch (Exception ex)
                {
                    await transaction.RollbackAsync(cancellationToken);
                    _logger.LogError($"检验支付事务失败: {ex.Message}");
                    throw;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"检验支付失败: {ex.Message}");
                throw new InvalidOperationException($"检验支付失败: {ex.Message}");
            }
        }
    }
} 